﻿using System;
using System.Collections.Generic;
using System.Text;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.SystemUI;
using System.Diagnostics;
using ESRI.ArcGIS.esriSystem;

namespace CanSWAT.Util
{
    /// <summary>
    /// List All ArcMap Commands and execute
    /// </summary>
    class ArcMapCommands
    {
        private IApplication _application;
        private SortedDictionary<string, ICommand> _commands;

        public ArcMapCommands(IApplication app)
        {
            _application = app;
        }

        #region Run one ArcMap Command

        /// <summary>
        /// run one command corresponding to given clsid
        /// </summary>
        /// <param name="clsid"></param>
        private bool runArcMapCommand(string clsid)
        {
            //this run a specific command
            UID cmdID = new UIDClass();
            cmdID.Value = clsid;    //this is the ArcSWAT
            ICommandItem cmd =
                _application.Document.CommandBars.Find(cmdID, false, false);
            if (cmd != null && cmd.Type == esriCommandTypes.esriCmdTypeCommand && cmd.Command != null)
            {
                if (cmd.Command.Enabled) //this would initialze the Environment variables (e.g. the project location) in ArcSWAT
                {
                    cmd.Command.OnClick();
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// run "run swat model" command
        /// </summary>
        public void ArcSWAT_RunModel()
        {
            if(!runArcMapCommand("{29C190A5-808B-4D2D-B259-091F8A00B7AD}"))
                CanSWAT.showInformationWindow("ArcSWAT simulation function only works when ArcSWAT project is opened! Please check if the ArcSWAT is installed and if the ArcSWAT project have been opened."); //The IApplication will be used to initialized ArcSWAT global variables. So, if IApplication is null, it the run swat menu will be disabled.
        }

        /// <summary>
        /// run "Export output" command to read outputs to mdb
        /// </summary>
        public void ArcSWAT_ExportOuput()
        {
            if (!runArcMapCommand("{97CE444E-BADA-45E2-BA50-63946D515312}"))
                CanSWAT.showInformationWindow("Please run the model first!");
        }

        #endregion

        #region Try to get all ArcmMap Commands. Just as a practise.

        private void execute()
        {
            ExecuteArcMapCommandsFrm frm = new ExecuteArcMapCommandsFrm(Commands);
            frm.ShowDialog();
        }

        private SortedDictionary<string, ICommand> Commands
        {
            get
            {
                if (_commands != null) return _commands;

                _commands = new SortedDictionary<string, ICommand>();

                //Only work with ArcMap application types, not ArcCatalog, ArcGlobe, ArcToolBox, etc.
                if (!(_application is ESRI.ArcGIS.ArcMapUI.IMxApplication)) return _commands;          

                // Set up GUID object for 'ESRI Mx Commands' component category
                ESRI.ArcGIS.esriSystem.UID uid_MxCommands = new ESRI.ArcGIS.esriSystem.UIDClass();
                uid_MxCommands.Value = (System.Object)("{B56A7C42-83D4-11D2-A2E9-080009B6F22B}"); // Explict Cast
                
                // Set up the category factory.
                ICategoryFactory categoryFactory = new ESRI.ArcGIS.esriSystem.CategoryFactoryClass();
                categoryFactory.CategoryID = uid_MxCommands;

                // Go through each member of the category, and if it is a toolbar try to find it in the document
                ICommand cmd = getNextCommand(categoryFactory);

                while (cmd != null)
                {
                    if (cmd.Category.ToLower().Contains("swat") && !_commands.ContainsKey(cmd.Caption))
                    {
                        _commands.Add(cmd.Caption, cmd);
                        Debug.WriteLine(cmd.Category + "," + cmd.Caption);
                    }

                    cmd = getNextCommand(categoryFactory);                     
                }
                return _commands;
            }
        }

        private ICommand getNextCommand(ICategoryFactory fact)
        {
            try
            {
                object o = fact.CreateNext();
                if (o == null) return null;
                if (o is ICommand)
                {
                    ICommand cmd = (ESRI.ArcGIS.SystemUI.ICommand)o;
                    try
                    {
                        string caption = cmd.Caption;
                        return cmd;
                    }
                    catch
                    {
                        return getNextCommand(fact);
                    }
                }
                return getNextCommand(fact);
            }
            catch
            {
                return getNextCommand(fact);
            }
        }

        #endregion

        /// <summary>
        /// get all existing extensions
        /// </summary>
        private void getExtension()
        {
            //output all extensions
            //IExtensionManager mger = m_application as IExtensionManager;
            //for (int i = 0; i < mger.ExtensionCount; i++)
            //    CanSWAT.debugInformation(string.Format("Name = {1}, CLSID = {0}",
            //        mger.get_ExtensionCLSID(i).Value,
            //        mger.get_Extension(i).Name));

            //12/6/2013 4:38:54 PM, Information : Name = ESRI Route Events Application Extension, CLSID = {0050490F-E5E4-463F-AC40-5121E4816743}
            //12/6/2013 4:38:54 PM, Information : Name = Overposter Validation, CLSID = {37025245-BBCC-4582-B46F-02C5307296F7}
            //12/6/2013 4:38:54 PM, Information : Name = Survey Analyst, CLSID = {73FFE82B-D2E3-4852-8EFD-B7B64745B7CB}
            //12/6/2013 4:38:54 PM, Information : Name = ESRI Representation Application Extension, CLSID = {9A8C77AD-4841-434B-9863-C948BE05B5C0}
            //12/6/2013 4:38:54 PM, Information : Name = ESRI Route Hatching Extension, CLSID = {AED6E9C7-C161-439D-B816-A9066A2A29FA}
            //12/6/2013 4:38:54 PM, Information : Name = Data Interoperability, CLSID = {B7F5E5C3-D500-49B4-91F5-CDAAC07DE9BF}
            //12/6/2013 4:38:54 PM, Information : Name = SWAT Watershed delineator, CLSID = {D05AD24B-3E18-412B-9BAE-48E54FDB8B85}
            //12/6/2013 4:38:54 PM, Information : Name = TabletPC Support, CLSID = {E32524C6-8C5D-4D7E-9302-E61680088EF3}
            //12/6/2013 4:38:54 PM, Information : Name = SMWindow, CLSID = {E8521349-795A-4E57-9900-907E7A09BA2D}
            //12/6/2013 4:38:54 PM, Information : Name = SWAT Project manager, CLSID = {F3E7388B-5E07-4878-9C90-05C94FEB0261}
            //12/6/2013 4:38:54 PM, Information : Name = SurveyAnalyst_ArcMapExtension, CLSID = {B679B84A-13FC-11D6-9269-00508B48AE82}
            //12/6/2013 4:38:54 PM, Information : Name = ESRI Object Editor, CLSID = {F8842F20-BB23-11D0-802B-0000F8037368}
            //12/6/2013 4:38:54 PM, Information : Name = Survey Analyst (Cadastral Editor), CLSID = {114D685F-99B7-4B63-B09F-6D1A41A4DDC1}
            //12/6/2013 4:38:54 PM, Information : Name = Locator Database Extension, CLSID = {36C99530-923C-11D3-9F6B-00C04F6BDF06}

        }
    }
}
